home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / Mod / tplter.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  21.2 KB  |  847 lines

  1.  
  2. /******************************************************************************
  3.  
  4.     MODULE
  5.     tplter.c
  6.  
  7.     DESCRIPTION
  8.     ein kleines kommando, welches
  9.     ein Templatefile einliest,
  10.     das bestimmte Platzhalter enthaelt
  11.     und dann das verwendbare Ergebnis
  12.     in den aktuellen Text einbindet.
  13.  
  14.     NOTES
  15.     * for XDME some features of flexprintf were commented out
  16.     * that module is highly experimental
  17.  
  18.     BUGS
  19.        ?
  20.  
  21.     TODO
  22.     * linenumber in read_file
  23.     * check for success in flexprintf
  24.     * flexSCANf needs to be created - but that thing needs a
  25.       little bit more work, since we can't parse line by line
  26.     * another version of that module might support loops, conditionals
  27.       and subtemplates - lets see
  28.  
  29.     EXAMPLES
  30.  
  31.     SEE ALSO
  32.  
  33.     INDEX
  34.  
  35.     HISTORY
  36.     17-08-93 b_noll created
  37.     18-08-93 b_noll xdme-interface
  38.     15-06-94 b_noll added another flexprintf-version
  39.     15-08-94 b_noll added to the 1.83.** tree (no DynCom features)
  40.     01-10-94 b_noll introduced DEFMESSAGE
  41.  
  42.     PRIVATE
  43.     we need access to the following functions:
  44.         do_command();
  45.         do_insertwrite();
  46.         getvar();
  47.         COM_Add(), COM_Lock(), COM_Remove()
  48.  
  49.         fopen, fclose, xefgets may be replaced by Dos-Based Open, Close, [own-creation]
  50.         malloc && free may be replaced by Exec-Based AllocVec, FreeVec
  51.  
  52.     structures:
  53.         globalflags;
  54.         Ep;
  55.         av
  56.  
  57. ******************************************************************************/
  58.  
  59. /**************************************
  60.         Includes
  61. **************************************/
  62.  
  63. #include "defs.h"
  64. /* #include "COM.h" */
  65. /* #include "libs/AUTO.h" */
  66.  
  67. /**************************************
  68.         Global Variables
  69. **************************************/
  70.  
  71.  
  72. /**************************************
  73.         Internal Defines & Structures
  74. **************************************/
  75.  
  76. /* we do not need that structure in XDME */
  77. #ifndef   STREAM
  78. #define   STREAM APTR
  79. #endif /* STREAM */
  80.  
  81. /**************************************
  82.         Internal Variables
  83. **************************************/
  84.  
  85. static const char * mod_name = "Templater";
  86.  
  87. /**************************************
  88.         Internal Prototypes
  89. **************************************/
  90.  
  91. BOOL         flexprintf (STREAM*, BOOL (*)(STREAM*, STRPTR), STRPTR, STREAM*, STRPTR (*)(STREAM*, STRPTR));
  92. char*         mygetv    (APTR*  , char* );
  93. BOOL         myfputs    (FILE** , char* );
  94.  
  95. /**************************************
  96.         Macros
  97. **************************************/
  98. //DEFMESSAGE( _TPLT_no_memory, "No Memory\n" )
  99. //DEFMESSAGE( _TPLT_no_query_name, "No name given" )
  100. DEFMESSAGE( _TPLT_file_not_found, "File not found" )
  101. //DEFMESSAGE( _TPLT_unexpected_end_of_query, "Unterminated variable query" )
  102. //DEFMESSAGE( _TPLT_no_query_result, "No value for variable" )
  103. #define ERROR_NO_NAME_OF_QUERY     /* error ("%s:\n%s!\n", mod_name, _TPLT_no_query_name); */
  104. #define ERROR_NO_VALUE_OF_QUERY  /* error ("s:\n%s %s!\n", mod_name, _TPLT_no_query_result, memo); */
  105. #define ERROR_UNTERMINATED_QUERY /* error ("%s:\n%s!\n", mod_name, _TPLT_unexpected_end_of_query ) */
  106. #define ERROR_NO_FILE         error ("%s:\n%s %s!\n", mod_name, _TPLT_file_not_found, name);
  107. #define ERROR_NO_MEMORY      /* error ("%s:\n%s!\n", mod_name, _TPLT_no_memory); */
  108.  
  109. #define INC(x) ++(x)
  110. #define DEC(x) --(x)
  111.  
  112.  
  113. /* MACROS 18-08-93 by b_noll */
  114. #define is_char(x)     (isalnum(x) || ((x) ==  '_') || ((x) == '.'))
  115. #define is_command(x)  (is_varstart(*(x)) && (*(x) == (x)[1]))
  116. #define is_comment(x)  (*(x) == '#')
  117.  
  118.  
  119. /* ---- definitions for "is_varstart" */
  120. #ifdef SLOW_VARSTART
  121. # define is_varstart(x) strchr(query_starts, x)
  122. #else
  123. # define is_varstart(x) (((x) == '$') || ((x) == '%'))
  124.             /*    ((x) == '%') */                  /* <<< use that line to enable only   '%'-variables */
  125.             /*    ((x) == '$') */                  /* <<< use that line to enable only   '$'-variables */
  126.             /* (((x) == '$') || ((x) == '%')) */ /* <<< use that line to enable '$' or '%'-variables */
  127. #endif
  128.  
  129.  
  130. /* ---- definitions for query-recognition */
  131. #define QUERY_START    "%$" /* <<< this line only has affect if SLOW_VARSTART is defined */
  132.  
  133. /* ---- definitions for bracket-recognition */
  134. #ifdef AMIGA
  135. # define BRACKET_OPEN  "(`[{<\253" /* the last one is '<<' */
  136. # define BRACKET_CLOSE ")']}>\273" /* the last one is '>>' */
  137. #else
  138. # define BRACKET_OPEN  "(`[{<"
  139. # define BRACKET_CLOSE ")']}>"
  140. #endif /* AMIGA */
  141.  
  142.  
  143.  
  144. #ifdef XDME
  145.  
  146. /* ---- XDME uses a subset of the possibles methods; */
  147. /*    we currently do only allow $(...) and $`...' */
  148. /*    to be recognized and replaced */
  149. # undef SLOW_VARSTART
  150. # undef is_varstart
  151. # undef QUERY_START
  152. # undef BRACKET_OPEN
  153. # undef BRACKET_CLOSE
  154.  
  155.  
  156. # define is_varstart(x) ((x) == '$')
  157. # define QUERY_START    "$"
  158. # define BRACKET_OPEN    "(`"
  159. # define BRACKET_CLOSE    ")'"
  160.  
  161. #endif /* XDME */
  162.  
  163. /**************************************
  164.         Implementation
  165. **************************************/
  166.  
  167.  
  168.  
  169.  
  170.  
  171. /* ---- there are currently 2 Versions of flexprintf here;
  172. **    the first - older - version was used over 'bout 1/2 a year
  173. **    and did not show any error; the second one is not yet really
  174. **    tested w/ "XDME", it was used with "Nyktos Ophthalmoi" for
  175. **    'bout 2 months.
  176. **    please do't ask me, why I created 2nd version, there was
  177. **    a reason, but I can't remember ... */
  178.  
  179. #ifdef OLD
  180.  
  181.  
  182. /*****************************************************************************
  183.  
  184.     NAME
  185.     flexprintf
  186.  
  187.     PARAMETER
  188.     STREAM*outstream;
  189.     ;BOOL (*writechar)  (STREAM*, char);
  190.     BOOL (*writestring)(STREAM*, STRPTR);
  191.     STRPTR format;
  192.     STREAM*instream;
  193.     STRPTR (*getstring)(STREAM*, STRPTR);
  194.  
  195.     RESULT
  196.     success
  197.  
  198.     RETURN
  199.     BOOL;
  200.  
  201.     DESCRIPTION
  202.     similar to C_sprintf but slightly different.
  203.  
  204.     wir parsen ein template, das
  205.     $(...) oder %(...) oder ${...} oder %{...} oder
  206.     $«...» oder %«...» oder $<...> oder %<...> oder
  207.     $[...] oder %[...] oder $`...' oder %`...'
  208.     als signalworte hat;
  209.     was zwischen den Klammern steht, wird an
  210.     getstring uebergeben; dessen Ergebnis
  211.     (wir erwarten IMMER strings) wird dann
  212.     eingesetzt.
  213.  
  214.     man kann die Funktion auf 2 sehr unterschiediche
  215.     Weisen verwenden:
  216.         wie sprintf - in diesem Falle ignoriert die
  217.     getfunktion das 2. Argument sondern gibt jedesmal den
  218.     "naechsten" wert zurueck
  219.         wie hier gedacht - in diesem falle liest die getfunktion
  220.     aus einem baum o.ae. den Wert, der der namen von arg2 traegt.
  221.  
  222.     NOTES
  223.     STREAM == APTR
  224.     format must not be const!
  225.  
  226.     not like in normal XDME-scripts there MUST be a form
  227.     of quotes around any variable!
  228.     for XDME "%" and "<...>" "«...»" "[...]" "{...}" were
  229.     disabled.
  230.  
  231.     BUGS
  232.     we do ignore the result of our writestring
  233.     and we do always return TRUE
  234.     (to fix - change "writestring..."
  235.           into     "if (!writestring...) return (FALSE);")
  236.  
  237.     EXAMPLES
  238.  
  239.     SEE ALSO
  240.  
  241.     INTERNALS
  242.  
  243.     HISTORY
  244.     21-07-93    b_noll  created
  245.     18-08-93    b_noll modified for XDME
  246.  
  247. ******************************************************************************/
  248.  
  249. BOOL flexprintf (STREAM* outstream, BOOL (*writestring)(STREAM*, STRPTR), STRPTR format, STREAM* instream, STRPTR (*getstring)(STREAM*, STRPTR))
  250. {
  251.     char    * cptr = format;
  252.     unsigned char curr;
  253.     unsigned char attn = 0;
  254.  
  255.     for (; (curr = *format) != 0; ++format) {
  256.     if (is_varstart(curr)) {
  257.         if (attn) *cptr = attn;
  258.         *format = 0;
  259.         writestring (outstream, cptr);
  260.         cptr = format;
  261.         attn = curr;
  262.         continue;
  263.     } /* if */
  264.  
  265.     if (attn) {
  266.         char scan = 0;
  267.  
  268.         switch (curr) {
  269.      /* some inconsistancies to XDME were commented out */
  270.      /* case '[': scan = ']'; break; */
  271.      /* case '«': scan = '»'; break; */
  272.      /* case '<': scan = '>'; break; */
  273.      /* case '{': scan = '}'; break; */
  274.         case '(': scan = ')'; break;
  275.         case '`': scan = '\''; break;
  276.         } /* switch */
  277.  
  278.         if (scan) {
  279.         char * memo;
  280.         char * rslt;
  281.  
  282.         ++format;
  283.         memo = format;
  284.         while ((curr = *format) && !(curr == scan)) {
  285.             ++format;
  286.         } /* while */
  287.  
  288.         *format = 0;
  289.         if (*memo) {
  290.             rslt = getstring (instream, memo);
  291.             if (rslt) {
  292.             writestring (outstream, rslt);
  293.  
  294.             *format = scan;
  295.             attn    = 0;
  296.             cptr    = format+1;
  297.             continue;
  298.  
  299.             } else {
  300.             ERROR_NO_VALUE_OF_QUERY
  301.             } /* if */
  302.         } else {
  303.             ERROR_NO_NAME_OF_QUERY
  304.         } /* if */
  305.         *format = scan;
  306.         } /* if */
  307.  
  308.         *cptr = attn;
  309.         attn  = 0;
  310.     } /* if */
  311.     } /* for */
  312.     writestring (outstream, cptr);
  313.     return (TRUE);
  314.  
  315. } /* flexprintf */
  316.  
  317. #else /* !OLD */
  318.  
  319.  
  320. /*****************************************************************************
  321.  
  322.     NAME
  323.     flexprintf
  324.  
  325.     PARAMETER
  326.     STREAM*outstream;
  327.     BOOL (*writestring)(STREAM*, STRPTR);
  328.         ; we expect writestring to return <>0 on Success and
  329.         ; 0 in case of any Failure.
  330.     STRPTR tmplt;
  331.         ; Format is destroyed during the scan, we cannot
  332.         ; use const-strings in System with mem-protection
  333.     STREAM*instream;
  334.     STRPTR (*getstring)(STREAM*, STRPTR);
  335.  
  336.     RESULT
  337.     success
  338.  
  339.     RETURN
  340.     BOOL;
  341.  
  342.     DESCRIPTION
  343.     similar to C/sprintf but slightly different in usage and syntax:
  344.         while sending tmplt through "writestring(outstream,...)",
  345.     we do replace occurancies of [$%][[(`{|<]char-seq[])'}>] with
  346.     the string, that is returned by "getstring(instream, char-seq)";
  347.     the meaning of [$%] can be escaped by duplicating the character.
  348.  
  349.  
  350.     NOTES
  351.     * tmplt MUST NOT be const! (see BUGS)
  352.       for _flexprintf in any case and for flexprintf
  353.       as long as FLEXPRINT_BUFFER is not defined to 1
  354.  
  355.     * not like in normal Shell- or XDME-scripts there MUST be a form
  356.       of quotes around any variable!
  357.  
  358.     * formatting of replaced variables must be supported by the
  359.       get-function, if such features are needed.
  360.  
  361.     * between the brackets of a variable-query there must be at least
  362.       one char; empty variablenames are not allowed (also if Your getstring
  363.       knows, what is wanted), and lead to a break.
  364.  
  365.     * getstring returning NULL means an error has occured; we will break
  366.       for this reason. Empty strings should be given via "".
  367.       Furthermore we do not free the strings gotten from getstring(),
  368.       since we don't know, if they are static or not, so if these strings
  369.       are dynamically created, You should store them in a static variable.
  370.       my preferred way looks like the following:
  371.         char *getvar(void *x, char *n) {
  372.         static char *ptr = NULL;
  373.         if (ptr) free(ptr);
  374.         ptr = ...;
  375.         return ptr;
  376.         }
  377.  
  378.  
  379.     * not terminating a query will cause a break, if there is no other
  380.       query behind, else the result is not defined.
  381.  
  382.     * we use different macros to inticate the common errors, which are
  383.       recognized: ERROR_NO_NAME_OF_QUERY, ERROR_NO_VALUE_OF_QUERY and
  384.       ERROR_UNTERMINATED_QUERY, ERROR_NO_MEMORY; they are defined to do nothing, so You
  385.       might want to redefine them to Your needs.
  386.  
  387.     Please note, that "%$" and "(`[{<«"/")']}>»" may be changed via some
  388.     defines described below:
  389.  
  390.     * the macro "is_varstart" is used to recognize %/$ - You might want to
  391.       redefine it according to Your needs (see above for different examples)
  392.       if defined "SLOW_VARSTART" You can use the define "QUERY_START" to
  393.       define a list of characters, which may be used as start of a query-
  394.       indicator.
  395.  
  396.     * the defines "BRACKET_OPEN" and "BRACKET_CLOSE" can be used to define
  397.       the different open-brackets and their corresponding close-brackets
  398.       (see above for examples)
  399.  
  400.     * to gain more flexibility You may directly call _flexprintf()
  401.       which has the additional parameters query_starts ("$%"),
  402.       open_brackets ("([{...") and close_brackets (")]}...")
  403.  
  404.     BUGS
  405.     * tmplt is temporarily destroyed during the scan. this is done,
  406.       since we have no information about a necessary buffersize to
  407.       keep a string in, but we wanted to use string-operations instead
  408.       of character operations for writestring.
  409.       (the described behaiviour can be changed (at least for flexprintf,
  410.       not for _flexprintf) by defining FLEXPRINT_BUFFER to 1. (that toggle
  411.       makes flexprintf create a copy of the template and send the copy
  412.       to _flexprintf))
  413.  
  414.     EXAMPLES
  415.  
  416.     SEE ALSO
  417.  
  418.     INTERNALS
  419.     * Funktionsweise:
  420.       wir parsen ein template, das normalerweise
  421.       $(...) oder %(...) oder ${...} oder %{...} oder
  422.       $«...» oder %«...» oder $<...> oder %<...> oder
  423.       $[...] oder %[...] oder $`...' oder %`...'
  424.       als signalworte hat; sobald wir auf ein %/$ stossen, wird der
  425.       bisher geparste und nicht ausgegebene Teil des templates nach
  426.       writestring geschickt. Falls nach %/$ dann eine der Klammern kommt,
  427.       wird, was zwischen den Klammern steht, an getstring uebergeben,
  428.       dessen Ergebnis (wir erwarten IMMER strings) wird dann an
  429.       writestring geschickt. Um die Bedeutung von %/$ zu loeschen
  430.       muss das entsprechende Symbol dupliziert werden, nur eines der
  431.       beiden wird dann ausgegeben. Falls keine bracket folgt, ist eine
  432.       Verdopplung eigentlich unnoetig, sollte aber dennoch erfolgen.
  433.  
  434.     * Anwendung:
  435.       man kann die Funktion auf 2 sehr unterschiediche
  436.       Weisen verwenden:
  437.         wie sprintf - in diesem Falle ignoriert die
  438.       get-funktion das 2. Argument und gibt jedesmal den
  439.       "naechsten" wert zurueck
  440.         wie hier gedacht - in diesem falle liest die getfunktion
  441.       aus einem baum o.ae. den Wert, der der namen von arg2 traegt.
  442.  
  443.  
  444.     HISTORY
  445.     21-07-93    b_noll created
  446.     17-08-93    b_noll rewritten without "writechar()"
  447.     18-08-93    b_noll modified for XDME
  448.     01-05-94    b_null major rewrites ...
  449.  
  450. ******************************************************************************/
  451.  
  452.  
  453. BOOL _flexprintf (STREAM* outstream, BOOL (*writestring)(STREAM*, STRPTR), STRPTR tmplt, STREAM* instream, STRPTR (*getstring)(STREAM*, STRPTR), const STRPTR query_starts, const STRPTR open_brackets, const STRPTR close_brackets) {
  454.     unsigned char *memo = tmplt;
  455.     unsigned char  curr;
  456.     unsigned char  attn = 0;
  457.  
  458.     for (; (curr = *tmplt) != 0; ++tmplt) {
  459.  
  460.     /* ---- seems, that we are starting a query, output all chars up to here, mark the pos w/ memo */
  461. #ifdef SLOW_VARSTART
  462.     if (strchr(query_starts, curr))
  463. #else
  464.     if (is_varstart(curr))
  465. #endif
  466.     {
  467.  
  468.         /* ---- previous char was the same? - then allow output of one of'em */
  469.         /*        that hack was done to allow something like escaping; now we  */
  470.         /*        forbid a query by preceding it with two the same varstarts     */
  471.         if (curr == attn) {
  472.         memo = tmplt;
  473.         attn = 0;
  474.         continue;
  475.         } /* if */
  476.  
  477.         /* ---- output the tmplt up to this point and     */
  478.         /*        mark the position with an additional ptr  */
  479.         /*        keep also a copy of varstart to recognize */
  480.         /*        duplicates in order to ignore them          */
  481.  
  482.         /* ---- we do temporarily modify tmplt here!!!! */
  483.         *tmplt = 0;
  484.         if (!writestring (outstream, memo)) {
  485.         *tmplt = curr;
  486.         return FALSE;
  487.         } /* if */
  488.         *tmplt = curr;
  489.  
  490.         memo   = tmplt;
  491.         attn   = curr;
  492.         continue;
  493.     } /* if varstart */
  494.  
  495.     if (attn) {
  496.         unsigned char scan = 0;
  497.  
  498.         attn    = 0;
  499.  
  500.         /* ---- check, if the current character is an open-bracket    */
  501.         /*        and get the close-bracket, that is correponding to    */
  502.         /*        this open-bracket                    */
  503.         {
  504.         int i;
  505.         for (i = 0; open_brackets[i]; ++i) {
  506.             if (curr == open_brackets[i]) {
  507.             scan = close_brackets[i];
  508.             break;
  509.             } /* if */
  510.         } /* for */
  511.         }
  512.  
  513.         /* ---- we found a bracket after var_start */
  514.         if (scan) {
  515.         char * rslt;
  516.  
  517.         /* ---- skip the open-bracket */
  518.         ++tmplt;
  519.  
  520.         /* ---- seach the close-bracket */
  521.         while ((curr = *tmplt) && !(curr == scan))
  522.             ++tmplt;
  523.  
  524.         /* ---- make sure we have found a terminating close-bracket */
  525.         if (!curr) {
  526.             ERROR_UNTERMINATED_QUERY
  527.             return FALSE;
  528.         } /* if */
  529.  
  530.         /* ---- make sure we have got at least one char */
  531.         /*    between the backets            */
  532.         if (tmplt == memo + 2) {
  533.             ERROR_NO_NAME_OF_QUERY
  534.             return FALSE;
  535.         } /* if */
  536.  
  537.         /* ---- query for the variable described between */
  538.         /*    the brackets                 */
  539.  
  540.         /* ---- here we do temporarily modify tmplt!!! */
  541.         *tmplt = 0;
  542.         rslt = getstring (instream, memo + 2);
  543.         *tmplt = scan;
  544.  
  545.         /* ---- make sure we got a valid string from getstring() */
  546.         if (!rslt) {
  547.             ERROR_NO_VALUE_OF_QUERY
  548.             return FALSE;
  549.         } /* if !rslt */
  550.  
  551.         /* ---- output the resultstring */
  552.         if (!writestring (outstream, rslt))
  553.             return FALSE;
  554.  
  555.         memo = tmplt+1;
  556.         } /* if bracket */
  557.     } /* if attn */
  558.     } /* for */
  559.  
  560.     if (!writestring (outstream, memo))
  561.     return FALSE;
  562.  
  563.     return TRUE;
  564. } /* _flexprintf */
  565.  
  566.  
  567.  
  568. BOOL flexprintf (STREAM* outstream, BOOL (*writestring)(STREAM*, STRPTR), STRPTR tmplt, STREAM* instream, STRPTR (*getstring)(STREAM*, STRPTR)) {
  569. #if defined(FLEXPRIN_BUFFER) && FLEXPRINT_BUFFER
  570.     char *dup;
  571.     BOOL  rslt;
  572.  
  573.     if (NULL == (dup = strdup(tmplt))) {
  574.     ERROR_NO_MEMORY
  575.     return FALSE;
  576.     } /* if */
  577.     rslt = _flexprintf(outstream, writestring, dup, instream, getstring, QUERY_START, BRACKET_OPEN, BRACKET_CLOSE);
  578.     free (dup);
  579.     return rslt;
  580. #else
  581.     return _flexprintf(outstream, writestring, tmplt, instream, getstring, QUERY_START, BRACKET_OPEN, BRACKET_CLOSE);
  582. #endif
  583. } /* flexprintf */
  584.  
  585.  
  586. #endif /* OLD */
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596. /*****************************************************************************
  597.  
  598.     NAME
  599.     read_file
  600.  
  601.     PARAMETER
  602.     char* tpltname;
  603.  
  604.     RESULT
  605.     success;
  606.  
  607.     RETURN
  608.     BOOL;
  609.  
  610.     DESCRIPTION
  611.     lese ein file ein,
  612.     bearbeite es nach den Vorgaben
  613.     und fuege es in den aktuellen kontext ein
  614.  
  615.     NOTES
  616.     beim einlesen des Files werden alle zeilen, die mit
  617.     $$ (oder %%) beginnen separat interpretiert, und nicht
  618.     wieder ausgegeben.
  619.  
  620.     BUGS
  621.  
  622.     EXAMPLES
  623.  
  624.     SEE ALSO
  625.  
  626.     INTERNALS
  627.  
  628.     HISTORY
  629.     21-07-93 b_noll created  for TEMPLATER
  630.     18-08-93 b_noll modified for XDME
  631.  
  632. ******************************************************************************/
  633.  
  634. BOOL read_file (char* name)
  635. {
  636.     char * buffer;
  637.     char * b2;
  638.     FILE * fi;
  639.     long   len;
  640.     BOOL   success = FALSE;
  641.  
  642.     if (name && *name) {
  643.     if ((buffer = malloc(MAXLINELEN))) {
  644.         if ((fi = fopen (name, "r"))) {
  645.         success = TRUE;
  646.         while (success && (len = xefgets (fi, buffer, MAXLINELEN)) >= 0) {
  647.             b2 = buffer;
  648. /* printf (">%s",buffer); */
  649.             if (is_command(b2)) {
  650.             if (is_comment(buffer+2)) continue;
  651.             success = do_command (buffer+2);
  652.             } else {
  653.             b2 = buffer + len;
  654.             *b2 = '\n';
  655.             ++b2;
  656.             *b2 = 0;
  657.  
  658.             success = flexprintf (NULL, (APTR)myfputs, buffer, NULL, (APTR)mygetv);
  659.  
  660.             } /* if */
  661.         } /* while */
  662.         fclose (fi);
  663.         } else {
  664.         ERROR_NO_FILE
  665.         } /* if */
  666.  
  667.         free (buffer);
  668.     } else {
  669.         nomemory();
  670.     } /* if */
  671.     } /* if */
  672.     return (success);
  673. } /* read_file */
  674.  
  675. /***************************************************
  676.         XDME ADAPTION 18-08-93
  677. ***************************************************/
  678.  
  679.  
  680. /* get a variable - XDME ignores arg1 */
  681. /* currently (20-10-93) we can NOT use a const char* name */
  682.  
  683. #if 1
  684.  
  685.  
  686. char* mygetv (APTR db, char* name)
  687. {
  688.     static char tmp_buf[256];
  689.     int  len;
  690.     char*template = "%s";
  691.  
  692. /* PrintF ("mygetVAR: <%s>\n", name); */
  693.  
  694.     if (!name) return (NULL);
  695.  
  696.     strcpy (tmp_buf, name);
  697.     name = tmp_buf;
  698.  
  699.     len = strlen (name);
  700.  
  701.     { /* cut trailing whitespace */
  702.     char * dummy;
  703.     dummy = name + len - 1;
  704.  
  705.     while (dummy > name && isspace(*dummy)) {
  706.         *dummy = 0;
  707.         --dummy;
  708.     } /* while */
  709.     }
  710.  
  711.     while (isspace(*name)) {++name;}
  712.  
  713.     {
  714.     char* dummy = name;
  715.  
  716.     /* find postpended SPRINTF-tplt */
  717.     while (*dummy && (*dummy != ':')) ++dummy;
  718.     if (*dummy && dummy[1]) { /* has a postpended sPrintF - template */
  719.         template = dummy + 1;
  720.  
  721.         /* Remove Whitespace between name and Template */
  722.         --dummy;
  723.         while (isspace(*dummy) && dummy > name) --dummy;
  724.         ++dummy;
  725.         *dummy = 0;
  726.     } /* if */
  727.     }
  728.  
  729.     {
  730.     if ((name = getvar(name))) {
  731.         sprintf (tmp_buf, template, name, name, name, name);
  732.         return (tmp_buf);
  733.     } /* if */
  734.     }
  735.  
  736.  
  737.  
  738.     return (NULL);
  739. } /* mygetv */
  740.  
  741. #else
  742.  
  743. char* mygetv (APTR* db, char* name)
  744. {
  745.     char * x;
  746. #if 0
  747.     if (x = getvar (name)) {
  748.     strcpy (tmp_buffer, x);
  749.     free   (x);
  750.     return (tmp_buffer);
  751.     } else
  752. #endif
  753.     {
  754.     char* dummy = name;
  755.     char* tpl   = "%s";
  756.     char  sec;
  757.  
  758.     /* find postpended SPRINTF-tplt */
  759.  
  760.     while (*dummy && (*dummy != ':')) ++dummy;
  761.     if (*dummy && dummy[1]) { /* has a postpended sPrintF - template */
  762.         tpl = dummy + 1;
  763.     } /* if */
  764.  
  765. #if 0
  766.     /* Remove Whitespace between name and Template */
  767.     --dummy;
  768.     while (isspace(*dummy) && dummy > name) --dummy;
  769.     ++dummy;
  770. #endif
  771.     sec    = *dummy;
  772.     *dummy = 0;
  773.  
  774.     if ((x = getvar (name))) {
  775.         sprintf(tmp_buffer, tpl, x);
  776.         free   (x);
  777.         return (tmp_buffer);
  778.     } /* if */
  779.     *dummy = sec;
  780.     } /* if */
  781.     return (NULL);
  782. } /* mygetv */
  783.  
  784. #endif
  785.  
  786.  
  787.  
  788. /* output a string - XDME ignores arg1 */
  789.  
  790. BOOL myfputs (APTR out, char* str)
  791. {
  792.     if (!*str) return (TRUE);
  793.     av[0] = "insert";
  794.     av[1] = str;
  795.     do_insertwrite();
  796.     return (BOOL)!IS_ABORTED();
  797. } /* myfputs */
  798.  
  799.  
  800.  
  801.  
  802. /***************************************************
  803.         XDME COMMAND INTERFACE 18-08-93
  804. ***************************************************/
  805.  
  806. /*DEFLONG #long READTEMPLATE
  807.  
  808. This command inserts @{B}file@{UB}.
  809. passing all lines starting with "$$" to EVAL
  810. (lines starting with "$$#" are ignored) and
  811. replacing all "$(...)" and "$`...'" by their
  812. values if matching variables do exist.
  813.  
  814. That function might be very useful for
  815. handling very formalistic structs, which
  816. do need only little work by user.
  817.  
  818. Since the parse is line-oriented, usage of
  819. linefeeds inside "$(...)" and "$`...' is
  820. forbidden; however expanded values might
  821. contain linefeeds
  822.  
  823. */
  824.  
  825. /*DEFHELP #cmd textedit,io READTEMPLATE filename - read in a file and replace all occurencies of $(varname) with the contents of that varname */
  826.  
  827. DEFUSERCMD("ReadTemplate", 1, CF_ICO, int, do_readtplt, (void),)
  828. {
  829.     read_file (av[1]);
  830.     return (1);
  831. } /* do_readtplt */
  832.  
  833.  
  834.  
  835.  
  836. #ifdef STATIC_COM
  837.  
  838.     COMMAND("readtemplate",        1, CF_ICO, (FPTR)do_readtplt )
  839.  
  840. #endif
  841.  
  842.  
  843. /******************************************************************************
  844. *****  END tplter.c
  845. ******************************************************************************/
  846.  
  847.